package com.jar.netty_demo.NIO;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.*;
import java.util.Iterator;
import java.util.Set;

public class NIOServer {
    public static void main(String[] args) throws IOException {
        //创建ServerSocketChannel
        ServerSocketChannel serverSocketChannel = ServerSocketChannel.open();
        //创建端口
        serverSocketChannel.bind(new InetSocketAddress(7777));
        //设置为非阻塞
        serverSocketChannel.configureBlocking(false);
        //创建selector
        Selector selector = Selector.open();
        //注册Channel到Selecetor中
        serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT);
        //循环等待客户端连接
        while (true) {
            //这里等待疫苗，如果没有事件发生，返回
            if (selector.select(1000) == 0) {
                System.out.println("服务器等待了1秒，无连接");
                continue;
            }
            /*
            如果返回的>0,就获取相关的selectionKey集合
            1、如果返回的>0,表示已经获取到关注的事件
            2、select.selectedKeys() 返回关注事件的集合
            */
            Set<SelectionKey> selectionKeys = selector.selectedKeys();
            //使用迭代器遍历Set<selectionKey>
            Iterator<SelectionKey> iterator = selectionKeys.iterator();
            while (iterator.hasNext()) {
                //获取到selectionKey
                SelectionKey key = iterator.next();
                //根据key对应的通道发生的事件做相应处理
                // 如果是OP_ACCEPT,有新的客户端连接，则该客户端生成一个SocketChannel
                if (key.isAcceptable()) {
                    //获取SocketChannel
                    SocketChannel socketChannel = serverSocketChannel.accept();
                    System.out.println("客户端连接成功，生成了一个socketChannel" + socketChannel.hashCode());
                    //设置非阻塞
                    socketChannel.configureBlocking(false);
                    //注册SocketChannel,关注事件为OP_READ,同时关联一个ByteBuffer
                    socketChannel.register(selector, SelectionKey.OP_READ, ByteBuffer.allocate(1024));
                }
                // 如果是OP_READ状态
                if (key.isReadable()) {
                    //可读的就直接根据key获取channel
                    SocketChannel channel = (SocketChannel) key.channel();
                    //获取到该channel关联的Buffer
                    ByteBuffer buffer = (ByteBuffer) key.attachment();
                    //把channel中的数据读到ByteBuffer中
                    channel.read(buffer);
                    System.out.println("来自客户端的消息：" + new String(buffer.array()));
                }
                //把当先key删除，防止重复操作
                iterator.remove();

            }
        }
    }
}
